/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package za.co.pas.business.model;

import za.co.pas.business.abstracts.AbstractDataModel;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.Query;
import org.apache.log4j.Logger;
import za.co.pas.business.data.Country;
import za.co.pas.business.data.Province;
import za.co.pas.business.message.StatusMessage;
import za.co.pas.business.message.StatusMessageObject;

/**
 *
 * @author alabuschagne
 */
public class CountryDataModel extends AbstractDataModel
{
    private List<Country> countries = null;
    
    private static Logger logger = Logger.getLogger(UserDataModel.class);

    public Country getCountryUsingCode(String countryCode)
    {
        try
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_INFO, "Getting country using code " + countryCode, StatusMessageObject.SMO_TYPE_READ));
            Query q = em.createQuery("SELECT c FROM Country c WHERE c.code LIKE :code").setParameter("code", countryCode);
            //.setMaxResults(10);
            setConnectionOk(true);
            return (Country) q.getSingleResult();
        }
        catch (NoResultException ex)
        {
            //This is not a error
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_WARN, "No results for country code " + countryCode, StatusMessageObject.SMO_TYPE_READ));
            logger.info(ex.getMessage());
        }
        catch (NonUniqueResultException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalStateException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalArgumentException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public List<Country> getCountries(boolean forced)
    {
        if((countries == null) || (forced))
        {
            countries = getCountriesFromDB();
            Collections.sort((List)countries);
        }
        return countries;
    }


    private List<Country> getCountriesFromDB()
    {
        try
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_INFO, "Getting all countries", StatusMessageObject.SMO_TYPE_READ));
            Query q = em.createQuery("SELECT c FROM Country c");
            setConnectionOk(true);
            return (List<Country>) q.getResultList();
        }
        catch (NoResultException ex)
        {
            //This is not a error
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_WARN, "No results for countries", StatusMessageObject.SMO_TYPE_READ));
            logger.info(ex.getMessage());
        }
        catch (NonUniqueResultException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalStateException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalArgumentException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public Province getProvinceUsingCode(String code)
    {
        try
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_INFO, "Getting province using code " + code, StatusMessageObject.SMO_TYPE_READ));
            Query q = em.createQuery("SELECT c FROM Province c WHERE c.code LIKE :code").setParameter("code", code);
            //.setMaxResults(10);
            setConnectionOk(true);
            return (Province) q.getSingleResult();
        }
        catch (NoResultException ex)
        {
            //This is not a error
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_WARN, "No results for province code " + code, StatusMessageObject.SMO_TYPE_READ));
            logger.info(ex.getMessage());
        }
        catch (NonUniqueResultException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalStateException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalArgumentException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public List<Province> getProvincesUsingCountry(Country country)
    {
        try
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_INFO, "Getting provinces using country ", StatusMessageObject.SMO_TYPE_READ));
            Query q = em.createQuery("SELECT c FROM Province c WHERE c.country = :country").setParameter("country", country);
            //.setMaxResults(10);
            setConnectionOk(true);
            return (List<Province>) q.getResultList();
        }
        catch (NoResultException ex)
        {
            //This is not a error
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_WARN, "No results for provinces ", StatusMessageObject.SMO_TYPE_READ));
            logger.info(ex.getMessage());
        }
        catch (NonUniqueResultException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalStateException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        catch (IllegalArgumentException ex)
        {
            firePropertyChange(new StatusMessage(StatusMessageObject.SMO_ERROR, "Reading error: " + ex.getMessage(), StatusMessageObject.SMO_TYPE_READ));
            logger.error(ex.getMessage(), ex);
        }
        return null;
    }

    public void add(Country c)
    {
        if(countries == null)
        {
            countries = new LinkedList<Country>();
        }
        countries.add(c);
    }

    public void add(Country country, Province p)
    {
        country.add(p);
        p.setCountry(country);
    }
}
